﻿
Imports Microsoft.DirectX.Direct3D

Namespace NPCs

    Module mNPCList

        Public Const NPC_AnimSpeed As Long = 5000000

        Public Structure NPCDesc

            Dim ID As Long

            Dim Name As String
            Dim CMD As String

            Dim Shape As Integer

            Dim mAnim As GUI.MirAnimation

            Dim mChatText As String
            Dim mChatTimeout As Long

            Dim mXCoord As Integer
            Dim mYCoord As Integer

        End Structure

        'list of MirActor classes that define the other Characters
        Public lstNPC As New SortedDictionary(Of Long, NPCDesc)

        Public Sub ClearList()

            Do Until lstNPC.Count = 0

                Dim E As IEnumerator(Of NPCDesc) = lstNPC.Values.GetEnumerator()

                E.MoveNext()
                E.Current.mAnim.Destroy()
                lstNPC.Remove(E.Current.ID)

            Loop

            'clear the character list
            lstNPC.Clear()

        End Sub

        Public Sub AddNPC(ByRef info As EvoLib.Protocol.NPCAddInfo)


            If lstNPC.Count > 0 Then

                Dim E As IEnumerator(Of NPCDesc) = lstNPC.Values.GetEnumerator()

                Do While E.MoveNext
                    If E.Current.ID = info.ID_NPC Then Exit Sub
                Loop

            End If

            Dim obj As New NPCDesc

            'todo: fill npc desc
            obj.ID = info.ID_NPC
            obj.Name = info.Name
            obj.Shape = info.Shape
            obj.CMD = info.CMD
            obj.mXCoord = info.X
            obj.mYCoord = info.Y

            Dim anim As GUI.Animation = New GUI.Animation(ImgLibs.NPC, (info.Shape * 100) + 1, GetNPCAnimCount((info.Shape * 100) + 1), NPC_AnimSpeed)
            obj.mAnim = New GUI.MirAnimation(GameWindow.GameWin, "NPC" & info.ID_NPC, 0, 0, True)
            obj.mAnim.StartAnim(anim, True)

            AddHandler obj.mAnim.Click, AddressOf NPCClick

            lstNPC.Add(info.ID_NPC, obj)

        End Sub

        Private Function GetNPCAnimCount(start As Integer) As Integer

            Dim C As Integer

            Do Until Libs.NPC.Image(start + C).HasImage = False

                C += 1

            Loop

            Return C

        End Function

        Public Sub NPCClick(name As String)

            Static bouncetimeout As Long

            If Left(name, 3) = "NPC" Then

                Dim ID_NPC As Long = CLng(Right(name, name.Length - 3))

                If bouncetimeout < DateTime.Now.Ticks Then

                    bouncetimeout = DateTime.Now.AddMilliseconds(500).Ticks

                    If lstNPC.ContainsKey(ID_NPC) Then

                        Dim npccall As NPCCall
                        npccall.CMD = lstNPC(ID_NPC).CMD
                        npccall.ID_NPC = lstNPC(ID_NPC).ID

                        Dim pkt As Packet
                        pkt.PacketType = GamePacketType.NPCCall
                        pkt.PacketOpCode = PacketOpCode.Enquiry
                        pkt.Username = Globals.sUsername

                        ClientSock.gSock.SendData(MakePacket(pkt, npccall, Globals.Crypto))

                    End If
                End If
            End If

        End Sub

        Public Sub RemoveNPC(ByRef id As Integer)

            If lstNPC.Count = 0 Then Exit Sub

            Dim E As IEnumerator(Of NPCDesc) = lstNPC.Values.GetEnumerator()

            Do While E.MoveNext

                If e.Current.ID = id Then
                    E.Current.mAnim.Destroy()
                    lstNPC.Remove(E.Current.ID)
                    Exit Sub
                End If

            Loop

        End Sub

        Public Sub DrawNPCs(ByRef mode As Globals.DrawingMode, ByRef offsetX As Integer, ByRef offsetY As Integer, ByRef originX As Integer, ByRef originY As Integer, ByRef defaultZ As Single, ByRef tc As Long)

            If Not (mode = Globals.DrawingMode.Normal Or mode = Globals.DrawingMode.Text) Then Exit Sub

            If lstNPC.Count = 0 Then Exit Sub

            Dim c As Integer = lstNPC.Count
            'Dim tmpChar As Character

            Dim E As IEnumerator(Of NPCDesc) = lstNPC.Values.GetEnumerator()

            Do While E.MoveNext
                With e.Current

                Dim z As Single
                Dim dx As Integer
                Dim dy As Integer

                dx = offsetX + ((.mXCoord - originX) * Constants.TileWidth)
                dy = offsetY + ((.mYCoord - originY) * Constants.TileHeight)
                    z = (defaultZ - (((.mYCoord - originY)) * 0.005F)) - 0.003F


                If mode = Globals.DrawingMode.Normal Then

                    .mAnim.SetPos(dx, dy)
                    .mAnim.Draw(mode, 0, 0, z)

                Else

                        DirectX.ProFont9.DrawBorderTextEx(.Name, dx + (Constants.TileWidth / 2) - (DirectX.ProFont9.GetNormalTextWidth(.Name) / 2), dy - (Constants.TileHeight / 2), Color.White, Color.Black, Constants.GameTextZ)

                    If .mChatTimeout > tc Then

                        Dim tW As Integer = DirectX.ProFont9.GetNormalTextWidth(.mChatText)
                        If tW >= Constants.ChatMessageWidth Then tW = Constants.ChatMessageWidth
                        Dim tH As Integer = DirectX.ProFont9.GetNormalTextHeight(.mChatText, tW)
                        Dim tX As Integer = (dx + (Constants.TileWidth \ 2)) - (tW \ 2)
                        Dim tY As Integer = dy - CInt(CSng(Constants.TileHeight) * 2.4F)

                        'destination rectangle
                        Dim Dest As Rectangle = New Rectangle(tX, tY, tW, tH + Constants.TileHeight)
                        'DrawTextFormat flags
                        Dim fmt As Microsoft.DirectX.Direct3D.DrawTextFormat = Microsoft.DirectX.Direct3D.DrawTextFormat.Center Or _
                                                    Microsoft.DirectX.Direct3D.DrawTextFormat.ExpandTabs Or _
                                                    Microsoft.DirectX.Direct3D.DrawTextFormat.WordBreak Or _
                                                    Microsoft.DirectX.Direct3D.DrawTextFormat.NoClip
                        'draw chat text
                        DirectX.ProFont9.DrawBorderTextEx(.mChatText, Dest, fmt, Color.White, Color.Black, Constants.GameTextZ)


                    End If

                End If
                End With
            Loop

        End Sub

        'Public Sub DrawCharactersAtPos(ByRef mode As Globals.DrawingMode, ByRef xcoord As Integer, ByRef ycoord As Integer, ByRef xpos As Integer, ByRef ypos As Integer, ByRef z As Single, ByRef tc As Long)

        'If lstCharacters(xcoord, ycoord) Is Nothing Then Exit Sub
        'Static c As Integer
        'c = lstCharacters(xcoord, ycoord).Count - 1
        'If c = -1 Then Exit Sub

        'Static isUpdated As Boolean
        'Static tmpChar As Character

        'For i As Integer = 0 To c

        'tmpChar = lstCharacters(xcoord, ycoord)(i)

        'With tmpChar

        'If .HeadAnimObj.mCurrentAnim.mDrawMode = mode Or .HumAnimObj.mCurrentAnim.mDrawMode = mode Or mode = Globals.DrawingMode.Tinted Then

        'If mode = .HumAnimObj.mCurrentAnim.mDrawMode Then

        'DoMovement(tmpChar, tc, isUpdated)

        'If isUpdated Then lstCharacters(xcoord, ycoord)(i) = tmpChar

        'End If

        '.HumAnimObj.Visible = True

        '.HumAnimObj.Draw(mode, xpos - .MovementOffsetX, ypos - .MovementOffsetY, z)

        '.HumAnimObj.Visible = False


        'End If

        'End With

        'Next

        'End Sub

        Public Sub UpdateNPCChat(ByRef msg As EvoLib.Protocol.NPCChatMsg, ByRef tc As Long)

            'if character list is empty, exit sub-routine
            If lstNPC.Count = 0 Then Exit Sub

            'iterate throught Actors in the Character list
            For Each npc As NPCDesc In lstNPC.Values

                'if the Name of the sender (of the chat message) matches the Actor Name THEN...
                If npc.ID = msg.ServerID Then

                    'Set the Chat Text string to the message string
                    npc.mChatText = npc.Name & ": " & msg.M.STR_MSG
                    'set the Chat Message timeout
                    npc.mChatTimeout = tc + Constants.ChatMessageDisplayTime

                    'exit sub-routine, nothing left to do
                    Exit Sub

                End If

            Next

        End Sub

        Public Function GetNPCFromPos(ByVal x As Integer, ByVal y As Integer) As NPCDesc

            For Each npc As NPCDesc In lstNPC.Values

                If npc.mXCoord = x And npc.mYCoord = y Then
                    Return npc
                End If

            Next

            Return Nothing

        End Function

        'Removes any character that has gone outside of the Play Area, e.g. 'Off-Screen'
        Public Sub FilterNPCs()

            'if there are no Characters in the list, Exit sub
            If lstNPC.Count = 0 Then Exit Sub

            Dim E As IEnumerator(Of NPCDesc) = lstNPC.Values.GetEnumerator()

            Do While E.MoveNext

                'check if this 'i' indexed character is outside the 'Play Area'
                If E.Current.mXCoord < GameWindow.CoordX - Constants.PlayAreaX Or _
                   E.Current.mYCoord < GameWindow.CoordY - Constants.PlayAreaY Or _
                    E.Current.mXCoord > GameWindow.CoordX + Constants.PlayAreaX Or _
                    E.Current.mYCoord > GameWindow.CoordY + Constants.PlayAreaY Then

                    'Character IS outside the play area, so...

                    'Remove this character
                    RemoveNPC(E.Current.ID)

                    'call self to remove further Invalidated Characters
                    FilterNPCs()
                    Exit Sub

                End If

            loop

        End Sub

    End Module

End Namespace